package com.ruoyi.business.service.impl;

import com.ruoyi.business.domain.BusCbsfyBO;
import com.ruoyi.business.domain.BusCbsxx;
import com.ruoyi.business.domain.BusFygl;
import com.ruoyi.business.domain.statistics.StatisticsBigDecimalBO;
import com.ruoyi.business.domain.vo.BusCbsfyVO;
import com.ruoyi.business.domain.vo.BusFyglSaveVO;
import com.ruoyi.business.mapper.BusFyglMapper;
import com.ruoyi.business.service.IBusFyglService;
import com.ruoyi.business.utils.BusOperatorUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.reflect.ScppReflectionUtils;
import com.ruoyi.web.core.config.FyglConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 费用管理Service业务层处理
 *
 * @author yaowei
 * @date 2021-07-02
 */
@Service
public class BusFyglServiceImpl implements IBusFyglService {

    @Autowired
    private FyglConfig fyglConfig;
    @Autowired
    private BusFyglMapper busFyglMapper;
    @Autowired
    private StatisticsBigDecimalService statisticsService;

    /**
     * 查询费用管理
     *
     * @param id 费用管理ID
     * @return 费用管理
     */
    @Override
    public BusFygl selectBusFyglById(Long id) {
        return busFyglMapper.selectBusFyglById(id);
    }

    /**
     * 查询费用管理列表
     *
     * @param busFygl 费用管理
     * @return 费用管理
     */
    @Override
    public List<BusFygl> selectBusFyglList(BusFygl busFygl) {
        return busFyglMapper.selectBusFyglList(busFygl);
    }

    /**
     * 新增费用管理
     *
     * @param busFyglSaveVO 费用管理
     * @return 结果
     */
    @Override
    public int insertBusFygl(BusFyglSaveVO busFyglSaveVO) {
        BusFygl busFygl = BeanUtils.copyBean(busFyglSaveVO, new BusFygl());
        BusOperatorUtils.setOperator(busFygl);
        return busFyglMapper.insertBusFygl(busFygl);
    }

    /**
     * 修改费用管理
     *
     * @param busFyglSaveVO 费用管理
     * @return 结果
     */
    @Override
    public int updateBusFygl(BusFyglSaveVO busFyglSaveVO) {
        Long id = busFyglSaveVO.getId();
        BusFygl busFygl = busFyglMapper.selectBusFyglById(id);
        BeanUtils.copyBean(busFyglSaveVO, busFygl);
        BusOperatorUtils.setOperator(busFygl);
        return busFyglMapper.updateBusFygl(busFygl);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int saveOrUpdate(List<BusFyglSaveVO> busFyglSaveList) {
        busFyglSaveList.forEach(busFyglSaveVO -> {
            Long id = busFyglSaveVO.getId();
            if (id == null) {
                this.insertBusFygl(busFyglSaveVO);
            } else {
                this.updateBusFygl(busFyglSaveVO);
            }
        });
        return busFyglSaveList.size();
    }

    /**
     * 批量删除费用管理
     *
     * @param ids 需要删除的费用管理ID
     * @return 结果
     */
    @Override
    public int deleteBusFyglByIds(Long[] ids) {
        return busFyglMapper.deleteBusFyglByIds(ids);
    }

    /**
     * 删除费用管理信息
     *
     * @param id 费用管理ID
     * @return 结果
     */
    @Override
    public int deleteBusFyglById(Long id) {
        return busFyglMapper.deleteBusFyglById(id);
    }

    /**
     * 根据承包商ID统计费用类型
     *
     * @param cbsId 承包商ID
     * @param year  费用年份
     * @return
     */
    @Override
    public List<StatisticsBigDecimalBO> statisticsByCbsId(Long cbsId, String year) {
        String statisticsYear = year;
        if (statisticsYear == null) {
            statisticsYear = getCurrentYear();
        }
        List<StatisticsBigDecimalBO> statisticsRsList = busFyglMapper.fylxStatistics(cbsId, statisticsYear);
        return statisticsService.getStatisticsByDictType(DICT_FYLX, statisticsRsList);
    }

    @Override
    public List<BusCbsfyVO> cbsfyList(String year) {
        if (year == null) {
            year = getCurrentYear();
        }
        String statisticsYear = year;
        Map<String, String> fyglMonthKeyMap = fyglConfig.getFyglMonthKey();
        List<Field> declaredFields = ScppReflectionUtils.getDeclaredFields(BusCbsfyVO.class,
                field -> fyglMonthKeyMap.containsKey(field.getName()));

        List<BusCbsxx> cbsxxList = busFyglMapper.cbsList(statisticsYear);
        return cbsxxList.stream().map(e -> {
            BusCbsfyVO busCbsfyVO = new BusCbsfyVO();
            busCbsfyVO.setCbsId(e.getId());
            busCbsfyVO.setCbsMc(e.getCbsName());
            List<BusCbsfyBO> busCbsfyBOList = busFyglMapper.cbsfyList(e.getId(), statisticsYear);
            this.setBusCbsfyFieldsValue(busCbsfyVO, declaredFields, busCbsfyBOList);
            return busCbsfyVO;
        }).collect(Collectors.toList());
    }

    private String getCurrentYear() {
        return String.valueOf(Calendar.getInstance().get(Calendar.YEAR));
    }

    private void setBusCbsfyFieldsValue(BusCbsfyVO busCbsfyVO, List<Field> fields, List<BusCbsfyBO> busCbsfyBOList) {
        Map<String, String> fyglMonthKeyMap = fyglConfig.getFyglMonthKey();
        fields.forEach(field -> {
            String fieldName = field.getName();
            String month = fyglMonthKeyMap.get(fieldName);
            BigDecimal monthFyje = getMonthFyje(month, busCbsfyBOList);
            ScppReflectionUtils.setField(field, busCbsfyVO, monthFyje);
        });
    }

    private BigDecimal getMonthFyje(String month, List<BusCbsfyBO> busCbsfyBOList) {
        if (month == null) {
            return BigDecimal.ZERO;
        }
        Optional<BusCbsfyBO> opt = busCbsfyBOList.stream().filter(e -> month.equals(e.getMonth())).findFirst();
        if (opt.isPresent()) {
            return opt.get().getFyje();
        } else {
            return BigDecimal.ZERO;
        }
    }
}
